package top.lshaci.learning.jsoup;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Jiaoxi20251
 *
 * @author lshaci
 * @version 1.0.3
 * @since 1.0.3
 */
@Slf4j
public class Jiaoxi20251 {

    // 定义文件保存的目录路径
    private static final String DIR_PATH = "D:\\Jiaoxi";

    // 文档的URL模板
    private static final String DOC_URL = "https://www.51jiaoxi.com/doc-{}.html";

    // 预览文档的API URL模板
    private static final String PREVIEW_URL = "https://www.51jiaoxi.com/api/document/preview?document_id={}&all=1";

    // 主函数入口
    public static void main(String[] args) throws Exception {
        String documentId = "14011129";
        docDownload(documentId);
    }

    /**
     * 下载文档及其图片，并合成PDF文件
     *
     * @param documentId 文档ID
     * @throws Exception 可能抛出的异常
     */
    private static void docDownload(String documentId) throws Exception {
        // 获取文档预览数据
        String respBody = HttpUtil.get(StrUtil.format(PREVIEW_URL, documentId));
        JSONObject data = JSON.parseObject(respBody).getJSONArray("data").getJSONObject(0);
        JSONArray formatSubsets = data.getJSONArray("format_subsets");
        for (int f = 0; f < formatSubsets.size(); f++) {
            JSONObject formatSubset = formatSubsets.getJSONObject(f);
            String title = formatSubset.getString("title").split("\\.")[0];
            mkdir(title);
            JSONArray previewFiles = formatSubset.getJSONArray("preview_files");
            List<File> fileList = CollUtil.newArrayList();
            for (int i = 0; i < previewFiles.size(); i++) {
                JSONObject previewFile = previewFiles.getJSONObject(i);
                String url = previewFile.getString("url");
                String fileUrl = previewFile.getString("file_url");
                String fileName = FileNameUtil.getName(fileUrl);
                fileList.add(download(url, title, fileName));
            }
            createPdf(title, fileList);
        }
    }

    /**
     * 创建PDF文件
     *
     * @param title    文档标题
     * @param fileList 图片文件列表
     * @throws IOException 可能抛出的IO异常
     */
    private static void createPdf(String title, List<File> fileList) throws IOException {
        String pdfPath = DIR_PATH + "\\" + title + ".pdf";
        try (PDDocument document = new PDDocument()) {
            for (File file : fileList) {
                PDPage page = new PDPage();
                PDRectangle mediaBox = page.getMediaBox();
                document.addPage(page);
                PDImageXObject image = PDImageXObject.createFromFileByContent(file, document);
                try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) {
                    contentStream.drawImage(image, 0, 0, mediaBox.getWidth(), mediaBox.getHeight());
                }
            }
            document.save(pdfPath);
        }
        log.debug("保存为PDF成功：{}", pdfPath);
    }

    /**
     * 下载图片
     *
     * @param url      图片URL
     * @param title    文档标题
     * @param fileName 文件名
     * @return 下载后的文件
     * @throws Exception 可能抛出的异常
     */
    private static File download(String url, String title, String fileName) throws Exception {
        log.debug("保存图片: {}: {}", title, url);
        File file = new File(DIR_PATH, title + "\\" + fileName);
        FileOutputStream out = new FileOutputStream(file);
        HttpUtil.download("https:" + url, out, true);
        TimeUnit.MILLISECONDS.sleep(500);
        return file;
    }

    /**
     * 创建文件夹
     *
     * @param title 文档标题，用于创建对应的文件夹
     */
    private static void mkdir(String title) {
        File dir = new File(DIR_PATH, title);
        log.debug("创建文件夹：{}", dir.getAbsolutePath());
        if (!dir.exists()) {
            dir.mkdirs();
        }
    }
}
